from graphics import *
from graphics.shapes import *
import base


def demo_3d_bar():        
    base.window("3d bar")
    w = viewport().width
    h = viewport().height
    d = h/6
    o = 10
    aw = w/4
    ah = h/4
    
    def bar(x,y,up, color):
        set_color(color)
        draw_3d_bar(x, y, aw, ah, d, up)
        set_color(C_WHITE)
        draw_3d_bar(x, y, aw, ah, d, up, fill=False)

    set_color(C_LGREEN)
    set_line_style(1,LINE_DOTTED)
    draw_line(w/2-o,   0, w/2-o, h)
    draw_line(w/2-o-aw,0, w/2-o-aw, h)
    draw_line(w/2+o,   0, w/2+o, h)
    draw_line(w/2+o+aw,0, w/2+o+aw, h)
    draw_line(0, h/2-o,    w, h/2-o)
    draw_line(0, h/2-o-ah, w, h/2-o-ah)
    draw_line(0, h/2+o,    w, h/2+o)
    draw_line(0, h/2+o+ah, w, h/2+o+ah)
    draw_rect(w/2-o-aw-d, h/2-o-ah-d, 2*(o+aw+d), 2*(o+ah+d), fill=False)
    
    set_line_style(1, LINE_SOLID)
    set_fill_style(FILL_CLOSE_INTERLEAVE)
    bar(w/2-o-aw, h/2-o-ah, BAR3D_UP_LEFT, C_RED)
    bar(w/2+o,    h/2-o-ah, BAR3D_UP_RIGHT, C_GREEN)
    bar(w/2-o-aw, h/2+o, BAR3D_DOWN_LEFT, C_BLUE)
    bar(w/2+o,    h/2+o, BAR3D_DOWN_RIGHT, C_YELLOW)
    
    base.wait()

def demo_reg_polygs():
    base.window("Regular polygons")
    K = 0.1
    NX = 3
    NY = 2
    W = viewport().width
    H = viewport().height
    R = min(1.0*W/NX, 1.0*H/NY)/3
    MAX = 50
    COLORS=(C_CYAN, C_RED, C_GREEN, C_BLUE, C_YELLOW, C_MAGENTA)

    class Polygon:
        def __init__(self, n, x, y, r, phi, color):
            self.speed = 0
            self.phi = phi
            self.x = x
            self.y = y
            self.r = r
            self.n = n
            self.color = color

        def step(self, time):
            self.speed -= (K*self.phi)*time
            if self.speed > MAX:
                self.speed = MAX
            elif self.speed < -MAX:
                self.speed = -MAX
            self.phi += self.speed

        def paint(self):
            set_fill_style(FILL_SOLID)
            set_color(self.color)
            draw_regular_polygon(self.n, self.x, self.y, self.r, self.phi)
            set_line_style(2)
            set_color(C_WHITE)
            draw_regular_polygon(self.n, self.x, self.y, self.r, self.phi, fill = False)
            draw_text(self.x, self.y, str(self.n), A_CENTER, A_CENTER)

    
    polygs = []
    for i in range(0,NX):
        for j in range(0,NY):
            polygs.append(Polygon(3+j*NX+i, int((0.5+i) * W/NX), int((0.5+j) * H/NY), R, base.rand(1001)-500, COLORS[j*NX+i]))

    while not key_pressed(0.1):
        begin()
        clear()
        for polygon in polygs:
            polygon.step(0.01)
            polygon.paint()
        end()

    base.wait()
            
    

def demo_stars():
    base.window("Stars")
    w = viewport().width
    h = viewport().height
    COGA = 14
    COGB = 10
    class Gear:
        def __init__(self, x, y, r, phi, delta, color, fill):
            self.x = x
            self.y = y
            self.r = r
            self.phi = phi            
            self.dir = dir
            self.n = int((2*math.pi*r)/COGA)
            self.color = color
            self.fill = fill
            self.delta = delta

        def rotate(self, dist):
            self.phi += dist * self.delta
            
        def paint(self):
            set_fill_style(self.fill)
            set_color(self.color)
            draw_star(self.n, self.x, self.y, self.r, self.r + COGB, 0, self.phi)
            set_color(C_WHITE)
            set_line_style(2)
            draw_star(self.n, self.x, self.y, self.r, self.r + COGB, 0, self.phi, fill=False)
            

    gears = [Gear(400,200,100, 0,+1, C_LRED, FILL_SOLID)]

    def add(r, color, fill):
        gear = gears[-1]
        gears.append(Gear(gear.x, gear.y, r, gear.phi, gear.delta, color, fill))

    def trans(x, y, color, fill):
        gear = gears[-1]
        r = round(math.sqrt((x-gear.x)**2+(y-gear.y)**2) - gear.r - COGB - 1)
        assert r > 1
        
        n = int((2*math.pi*r)/COGA)
        scale = 1.0*gear.n/n #each gear has a bit different sized cogs -> n is compared rather then r
        alpha = 180*math.atan2(y-gear.y, x - gear.x)/math.pi
        cor = 180 / n
        phi = 180 + alpha + scale * (alpha - gear.phi) + cor       
        delta = -scale * gear.delta
        gears.append(Gear(x, y, r, phi, delta, color, fill))
        print("t=(%d, %d) pos=(%d,%d)  alpha=%.2f  scale=%.2f  trans.phi=%.2f phi=%.2f"%(gear.x, gear.y, x, y, alpha, scale, gear.phi, phi))

    trans(150, 200, C_GREEN, FILL_SOLID)
    add(60, C_YELLOW, FILL_SOLID)
    trans(260,260, C_BLUE, FILL_SOLID)
    add(100, C_BLUE, FILL_INTERLEAVE)
    trans(600,10, C_MAGENTA, FILL_INTERLEAVE)
          
#    next(250, 280, 50, (C_GREEN, C_YELLOW))
#    next(600, 400, 330, (C_BROWN, C_MAGENTA))
#    next(h/2+h/6,w/2+w/6, 200 , C_MAGENTA)

    while not key_pressed(0.1):
        begin()
        clear()
        for gear in gears:
            gear.rotate(2)
            gear.paint()
        end()

    base.wait()
    

try:
    init(640, 480, title="Shapes Demo")
    demo_3d_bar()
    demo_reg_polygs()
    demo_stars()
except Close:
    pass
